#include "Camera.h"
#include <SEDebug/Log/Log.h>

namespace SEngine
{
    Camera &Camera::Translate(glm::vec3 translate)
    {
        m_pos += translate;
        return *this;
    }

    Camera &Camera::Rotate(glm::quat rotate, bool fixUp, glm::vec3 fixedUp)
    {
        m_rotate *= rotate;
        // m_rotate.x = glm::clamp(m_rotate.x, -89.0f, 89.0f);
        glm::vec3 front{1.0f, 0.0f, 0.0f};
        m_front = glm::normalize(glm::vec3(glm::mat4_cast(m_rotate) * glm::vec4{front, 0.0f}));
        // front.x = cos(glm::radians(m_rotate.x)) * cos(glm::radians(m_rotate.y));
        // front.y = sin(glm::radians(m_rotate.x));
        // front.z = cos(glm::radians(m_rotate.x)) * sin(glm::radians(m_rotate.y));
        if (fixUp) {
            m_up = fixedUp;
        } else {
            glm::vec3 up{0.0f, 1.0f, 0.0f};
            m_up = glm::normalize(glm::vec3(glm::mat4_cast(m_rotate) * glm::vec4{up, 0.0f}));
        }
        return *this;
    }

    glm::mat4 Camera::GetViewMatrix()
    { 
        return glm::lookAt(m_pos, m_pos + m_front, glm::normalize(m_up));
    }

    glm::mat4 Camera::GetProjectMatrix(int w, int h) const
    {
        float aspect = (float)w / h;
        switch (m_type)
        {
        case Perspective:
            return glm::perspective(glm::radians(m_fov), aspect, m_zNear, m_zFar);
        case Ortho:
            return glm::ortho(-m_size * aspect, m_size * aspect, -m_size, m_size, m_zNear, m_zFar);
        }
        return glm::mat4{1.0f};
    }
    
} // namespace SEngine

